import _ from 'lodash'
import dayjs from 'dayjs'
import { BaseService } from '../framework/base-service.js'

export default class RefreshService extends BaseService {
  static metadata = {
    name: 'refresh',
    dependencies: ['cache', 'rdb', 'bws'],  // 使用业务层 WebSocket 服务
    singleton: true
  }
  
  constructor(cache, rdb, bws) {
    super()
    this.cacheService = cache
    this.rdbService = rdb
    this.bwsService = bws
    this.refreshStats = new Map()
  }
  
  async onInit() {
    // 初始化任务配置
    this.tasks = this.config.get('biz.tasks') || {}
    
    // 初始化统计
    _.forEach(this.tasks, (config, name) => {
      if (config.action === 'biz.refresh') {
        this.refreshStats.set(name, {
          execCount: 0,
          errorCount: 0,
          lastExec: null,
          lastError: null
        })
      }
    })
  }
  
  async onInit() {
    console.log(`✅ RefreshService initialized with ${this.refreshStats.size} refresh tasks`)
  }
  
  /**
   * 执行单个刷新任务
   */
  async refreshTask(taskName) {
    const taskConfig = this.tasks[taskName]
    if (!taskConfig || taskConfig.action !== 'biz.refresh') {
      throw new Error(`Invalid refresh task: ${taskName}`)
    }
    
    const stats = this.refreshStats.get(taskName) || {
      execCount: 0,
      errorCount: 0,
      lastExec: null,
      lastError: null
    }
    
    const startTime = Date.now()
    
    try {
      console.log(`🔄 Refreshing ${taskName}...`)
      
      const { sql, schema } = taskConfig.params
      const result = await this.executeSqlAndCache(taskName, sql, schema)
      
      stats.execCount++
      stats.lastExec = {
        time: new Date().toISOString(),
        duration: Date.now() - startTime,
        rows: result.total
      }
      stats.lastError = null
      
      this.refreshStats.set(taskName, stats)
      
      console.info(`✅ Refreshed ${taskName}: ${result.total} rows, ${result.created} created, ${result.updated} updated, ${result.deleted} deleted`)
      
      return result
      
    } catch (error) {
      stats.execCount++
      stats.errorCount++
      stats.lastError = error.message
      stats.lastExec = {
        time: new Date().toISOString(),
        duration: Date.now() - startTime,
        error: error.message
      }
      
      this.refreshStats.set(taskName, stats)
      
      console.error(`❌ Refresh failed for ${taskName}:`, error.message)
      throw error
    }
  }
  
  /**
   * 执行SQL并更新缓存
   */
  async executeSqlAndCache(taskName, sql, schema) {
    // 替换SQL中的变量
    const oracleConfig = this.config.get('biz.oracle') || {}
    const finalSql = sql.replace(/\{(\w+)\}/g, (match, key) => {
      if (key === 'gpsname') return oracleConfig.gpsuser || 'xzgps'
      if (key === 'gpsuser') return oracleConfig.gpsuser || 'xzgps'
      return oracleConfig[key] || match
    })
    
    // 执行查询
    const result = await this.rdbService.execute(finalSql)
    const rows = result.rows || result || []
    
    if (rows.length === 0) {
      return { total: 0, created: 0, updated: 0, deleted: 0 }
    }
    
    // 处理每行数据
    const processedRows = await this.processRows(rows, taskName)
    
    // 更新缓存并计算差异
    const diff = await this.cacheService.updateWithDiff(`biz.${taskName}`, processedRows, 'CKEY')
    
    // 发送WebSocket事件
    if (diff.created.length > 0) {
      await this.wsManager.broadcast('updates', {
        type: 'data:created',
        namespace: `biz.${taskName}`,
        data: diff.created
      })
      this.eventBus.emit(`created:biz.${taskName}`, diff.created)
    }
    
    if (diff.updated.length > 0) {
      await this.wsManager.broadcast('updates', {
        type: 'data:updated',
        namespace: `biz.${taskName}`,
        data: diff.updated
      })
      this.eventBus.emit(`updated:biz.${taskName}`, diff.updated)
    }
    
    if (diff.deleted.length > 0) {
      await this.wsManager.broadcast('updates', {
        type: 'data:deleted',
        namespace: `biz.${taskName}`,
        data: diff.deleted
      })
      this.eventBus.emit(`deleted:biz.${taskName}`, diff.deleted)
    }
    
    return {
      total: rows.length,
      created: diff.created.length,
      updated: diff.updated.length,
      deleted: diff.deleted.length
    }
  }
  
  /**
   * 处理查询结果的每一行
   */
  async processRows(rows, taskName) {
    return _(rows)
      .map(row => {
        // 转换字段名为大写（Oracle风格）
        const upperRow = _.transform(row, (result, value, key) => {
          result[key.toUpperCase()] = value
        }, {})
        
        // 格式化时间字段
        if (upperRow.UPTIME) {
          upperRow.UPTIME = dayjs(upperRow.UPTIME).format('YYYY-MM-DD HH:mm:ss')
        }
        
        // 处理特定任务的字段映射
        this.applyTaskSpecificMapping(upperRow, taskName)
        
        return upperRow
      })
      .value()
  }
  
  /**
   * 应用任务特定的字段映射
   */
  applyTaskSpecificMapping(row, taskName) {
    // 处理坐标字段
    if (row.JD && row.WD) {
      row.BX = row.JD
      row.BY = row.WD
      delete row.JD
      delete row.WD
    }
    
    // 处理GPS坐标
    if (row.GPS_X && row.GPS_Y) {
      row.BX = row.GPS_X
      row.BY = row.GPS_Y
      delete row.GPS_X
      delete row.GPS_Y
    }
    
    // 任务特定处理
    switch (taskName) {
      case 'center':
      case 'station':
        row.TYPE = parseInt(row.TYPE) || 0
        break
        
      case 'hospital':
      case 'fivekind':
        row.TYPE = parseInt(row.TYPE) || 0
        if (!row.TYPENAME) row.TYPENAME = '医院'
        break
        
      case 'amb':
        row.TYPE = parseInt(row.CLFL) || 0
        delete row.CLFL
        break
        
      case 'emtstatus':
        row.TASK = row.STATUS || 0
        delete row.STATUS
        break
    }
  }
  
  /**
   * 刷新所有任务
   */
  async refreshAll() {
    const results = {}
    
    for (const [taskName, config] of Object.entries(this.tasks)) {
      if (config.action === 'biz.refresh') {
        try {
          results[taskName] = await this.refreshTask(taskName)
        } catch (error) {
          results[taskName] = { error: error.message }
        }
      }
    }
    
    return results
  }
  
  /**
   * 获取刷新统计
   */
  getStats() {
    const stats = {}
    
    this.refreshStats.forEach((value, key) => {
      stats[key] = { ...value }
    })
    
    const summary = {
      totalTasks: this.refreshStats.size,
      totalExec: _.sumBy([...this.refreshStats.values()], 'execCount'),
      totalErrors: _.sumBy([...this.refreshStats.values()], 'errorCount')
    }
    
    return {
      summary,
      tasks: stats
    }
  }
  
  registerRoutes(router) {
    // 手动触发刷新
    router.post('/api/refresh/:task', async (c) => {
      const taskName = c.req.param('task')
      
      if (taskName === 'all') {
        const result = await this.refreshAll()
        return c.json({ success: true, result })
      }
      
      try {
        const result = await this.refreshTask(taskName)
        return c.json({ success: true, result })
      } catch (error) {
        return c.json({ success: false, error: error.message }, 400)
      }
    })
    
    // 获取刷新统计
    router.get('/api/refresh/stats', async (c) => {
      const stats = this.getStats()
      return c.json(stats)
    })
  }
  
  registerScheduledTasks(scheduler) {
    // 注册每个刷新任务
    _.forEach(this.tasks, (config, name) => {
      if (config.action === 'biz.refresh' && config.cron) {
        scheduler.registerTask(
          `refresh:${name}`,
          {
            cron: config.cron,
            runOnInit: true,
            handler: () => this.refreshTask(name)
          }
        )
        
        console.info(`📅 Scheduled refresh task: ${name} (${config.cron})`)
      }
    })
    
    // 注册统计任务
    scheduler.registerTask(
      'refresh:stats',
      {
        cron: '0 */30 * * * *', // 每30分钟
        handler: () => {
          const stats = this.getStats()
          console.info('📊 Refresh Stats:', stats.summary)
          return stats
        }
      }
    )
    
    // 注册全量刷新任务
    scheduler.registerTask(
      'refresh:all',
      {
        cron: '0 0 3 * * *', // 每天凌晨3点
        handler: () => this.refreshAll()
      }
    )
  }
}